package com.travelsky.airchina.boarding.dao;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.Criterion;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.travelsky.airchina.boarding.util.PageUtil;


/**
 * 这是针对IGenericDAO接口的Hibernate实现，完成通用的CRUD操作。
 * 
 * @author wangguochen
 *
 * @param <T>POJO类
 * @param <ID>POJO类的主键标识符
 * @param <DAOImpl>针对每一个POJO类的DAO类实现 
 */
public abstract class GenericDAOHibernate<T, ID extends Serializable> extends HibernateDaoSupport{

	private Class<T> persistentClass;
	
	@SuppressWarnings("unchecked")
	public GenericDAOHibernate() {
		this.persistentClass = (Class<T>) ((ParameterizedType) getClass()
				.getGenericSuperclass()).getActualTypeArguments()[0];
	}
	
	public Class<T> getPersistentClass() {
		return persistentClass;
	}

	public T findById(ID id) {
		return (T)this.getHibernateTemplate().get(getPersistentClass(), id);
	}

	public T findById(ID id, boolean lock) {
		T entity;
		if (lock){
			entity = (T)this.getHibernateTemplate().get(getPersistentClass(), id,LockMode.UPGRADE);
		} else {
			entity = findById(id);
		}
		return entity;
	}

	public List<T> findAll() {
		return findByCriteria();
	}

	public T makePersistent(T entity) {
		try {
			//this.getHibernateTemplate().saveOrUpdate(entity);
			this.getHibernateTemplate().merge(entity);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return entity;
	}

	public void makeTransient(T entity) {
		this.getHibernateTemplate().delete(entity);
	}
	
	@SuppressWarnings("unchecked")
	protected List<T> findByCriteria(final Criterion... criterion) {
		HibernateCallback callback = new HibernateCallback() { 
			   public Object doInHibernate(Session session) throws HibernateException, 
			     SQLException {
					Criteria crit = session.createCriteria(getPersistentClass());
					for (Criterion c : criterion) {
						crit.add(c);
					}
					return crit.list();
			   } 
		};
		return this.getHibernateTemplate().executeFind(callback);
	}

	@SuppressWarnings("unchecked")
	public List findByQuery(String query, Map params,
			int firstResult, int maxResults, boolean isPaging) {
		Query queryObject = this.getSession().createQuery(query);
		if(params!=null){
			for (Iterator ite = params.keySet().iterator(); ite.hasNext();) {
		        String paramName = (String) ite.next();
		        if(params.get(paramName) instanceof List){
			        queryObject.setParameterList(paramName, (List)params.get(paramName));
		        }else{
			        queryObject.setParameter(paramName, params.get(paramName));
		        }
	        }
		}
		if (isPaging) {
			queryObject.setFirstResult(firstResult - 1);
			queryObject.setMaxResults(maxResults);
		}
		return queryObject.list();
	}
	@SuppressWarnings("unchecked")
	public int countHqlQuery(String query, Map params) {
		Query queryObject = this.getSession().createQuery(query);
		if(params!=null){
			for (Iterator ite = params.keySet().iterator(); ite
					.hasNext();) {
				String paramName = (String) ite.next();
		        if(params.get(paramName) instanceof List){
			        queryObject.setParameterList(paramName, (List)params.get(paramName));
		        }else{
					queryObject.setParameter(paramName, params.get(paramName));
		        }
			}
		}
		List<Long> list = queryObject.list();
		if(list!=null && list.size()>0 && list.get(0)!=null){
			return list.get(0).intValue();
		}else{
			return 0;
		}

	}
	/**
	 * 查询容器
	 * @param paging 分页容器 其中 curPage与needPaging两值需要传入
	 * @param countQuery 统计条件语句
	 * @param query 带有条件的查询语句
	 * @param params 查询条件
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List findQueryList(PageUtil pageUtil,
			String countQuery,String query, Map params) {
		List list = null;
		if (pageUtil != null && pageUtil.isNeedPaging()) {
			int totalRow = countHqlQuery(countQuery, params);
			pageUtil.setTotalRow(totalRow);
			pageUtil.sumPage();
			if (totalRow > 0) {
				list = findByQuery(query, params, pageUtil.getStartnum(), pageUtil
						.getMaxResult(), true);
			}
		} else {
			list = findByQuery(query, params, 0, 0, false);
			if (pageUtil != null) {
				pageUtil.setTotalRow(list.size());
				pageUtil.setCurPage(1);
			}
		}
		if (list == null)
			list = new ArrayList();
		return list;
	}
}

